package com.drakulo.games.ais.ui.component;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;

import com.drakulo.games.ais.core.Colony;
import com.drakulo.games.ais.core.GameData;
import com.drakulo.games.ais.core.Resource;
import com.drakulo.games.ais.core.ResourceHelper;
import com.drakulo.games.ais.core.Settings;
import com.drakulo.games.ais.ui.I18n;
import com.drakulo.games.ais.ui.ImageManager;
import com.drakulo.games.ais.ui.UIHelper;
import com.drakulo.games.ais.ui.component.button.TextButton;
import com.drakulo.games.ais.ui.twlbridge.RootPane;

import de.matthiasmann.twl.ComboBox;
import de.matthiasmann.twl.EditField;
import de.matthiasmann.twl.EditField.Callback;
import de.matthiasmann.twl.model.SimpleChangableListModel;

/**
 * This class displays and handle resource transfer between two colonies
 * 
 * @author Drakulo
 * 
 */
public class TransferWindow extends UIComponent {
	/** The combo selecting the source colony */
	private ComboBox<Colony> comboFrom;
	/** The combo selecting the destination colony */
	private ComboBox<Colony> comboTo;
	/** The cancel button */
	private TextButton closeButton;
	/** The send button */
	private TextButton sendButton;
	/** Resources of the source colony */
	private ResourceDisplay resourceDispFrom;
	/** Resources of the destination colony */
	private ResourceDisplay resourceDispTo;
	/** Text fields */
	private Map<Resource, EditField> fields;
	/** The colony list for combo boxes */
	private SimpleChangableListModel<Colony> colonyList;
	/** The TWL Root Panel */
	private RootPane rootPane;

	public TransferWindow(RootPane twlRootPane) {
		rootPane = twlRootPane;
		setWidth(300);
		setHeight(300);
		int x = Settings.WIDTH / 2 - getWidth() / 2;
		int y = Settings.HEIGHT / 2 - getHeight() / 2;
		setOX(x);
		setOY(y);

		final int comboWidth = 120;
		final int comboHeight = 18;

		colonyList = new SimpleChangableListModel<Colony>(
				GameData.getColonies());

		x += 10;
		y += 10;
		comboFrom = new ComboBox<Colony>(colonyList);
		comboFrom.setTheme("listbox");
		comboFrom.setSize(comboWidth, comboHeight);
		comboFrom.setPosition(x, y);
		comboFrom.addCallback(new Runnable() {

			@Override
			public void run() {
				System.out.println("From : " + comboFrom.getSelected());
				if (comboFrom.getSelected() == -1) {
					return;
				}
				Colony c = colonyList.getEntry(comboFrom.getSelected());
				resourceDispFrom.setMap(ResourceHelper.cloneMap(c
						.getResources()));
			}
		});
		twlRootPane.add(comboFrom);

		resourceDispFrom = new ResourceDisplay(twlRootPane, x, y + comboHeight
				+ 10);

		x = getOX() + getWidth() - 6 - 10 - comboWidth;
		comboTo = new ComboBox<Colony>(colonyList);
		comboTo.setTheme("listbox");
		comboTo.setSize(comboWidth, comboHeight);
		comboTo.setPosition(x, y);
		comboTo.addCallback(new Runnable() {

			@Override
			public void run() {
				if (comboTo.getSelected() == -1) {
					return;
				}
				Colony c = colonyList.getEntry(comboTo.getSelected());
				resourceDispTo.setMap(ResourceHelper.cloneMap(c.getResources()));
			}
		});
		twlRootPane.add(comboTo);

		resourceDispTo = new ResourceDisplay(twlRootPane, x, y + comboHeight
				+ 10);

		x = getOX() + 10 + 21;
		y += resourceDispTo.getHeight() + 9;
		fields = new HashMap<Resource, EditField>();
		Resource[] resources = Resource.values();
		for (Resource r : resources) {
			EditField ef = new NumberField();
			ef.setTheme("editfield");
			ef.setPosition(x, y += 25);
			ef.setSize(120, 15);
			twlRootPane.add(ef);
			fields.put(r, ef);
		}

		x = Settings.WIDTH / 2 - 5 - TextButton.DEFAULT_WIDTH;
		y = getOY() + getHeight() - 10 - TextButton.DEFAULT_HEIGHT;
		closeButton = new TextButton(I18n.get("global.close"));
		closeButton.setPosition(x, y);
		closeButton.bindTo(twlRootPane);
		closeButton.setActionHandler(new ActionHandler() {

			@Override
			public void run() {
				hide();
			}
		});

		x = Settings.WIDTH / 2 + 5;
		sendButton = new TextButton(I18n.get("global.send"));
		sendButton.setPosition(x, y);
		sendButton.bindTo(twlRootPane);
		sendButton.setActionHandler(new ActionHandler() {

			@Override
			public void run() {
				sendResources();

			}
		});

		hide();
	}

	@Override
	public void render(Graphics g) throws SlickException {
		if (!isShown()) {
			return;
		}
		UIHelper.drawWindow(g, getOX(), getOY(), getWidth(), getHeight());
		closeButton.render(g);
		sendButton.render(g);
		resourceDispFrom.render(g);
		resourceDispTo.render(g);

		int x = getOX() + 10;
		int y = getOY() + 10 + comboFrom.getHeight() + 10
				+ resourceDispFrom.getHeight();

		Resource[] resources = Resource.values();
		Image img;
		for (Resource r : resources) {
			img = ImageManager.getGfx(r.getGfxBase() + "-small");

			UIHelper.drawBlackBox(g, x, y, 20, 20);
			img.draw(x, y, r.getColor());

			y += 20 + 5;
		}
	}

	@Override
	public void update(Input input) throws SlickException {
		if (!isShown()) {
			return;
		}
		closeButton.update(input);
		sendButton.update(input);
		resourceDispFrom.update(input);
		resourceDispTo.update(input);

		updateSenderData();
		updateReseiverData();
	}

	public void show() {
		super.show();
		display(true);
		closeButton.show();
		sendButton.show();
		resourceDispFrom.show();
		resourceDispTo.show();
	}

	public void hide() {
		super.hide();
		display(false);
		closeButton.hide();
		sendButton.hide();
		resourceDispFrom.hide();
		resourceDispTo.hide();
	}

	private void display(boolean show) {
		comboFrom.setVisible(show);
		comboTo.setVisible(show);
		Resource[] resources = Resource.values();
		for (Resource r : resources) {
			fields.get(r).setVisible(show);
		}
	}

	private void sendResources() {
		final int from = comboFrom.getSelected();
		final int to = comboTo.getSelected();

		// 2 colonies must be selected
		if (from == -1 || to == -1) {
			// TODO play an error sound
			// TODO display an error message
			return;
		}

		// The colonies selected must be different!
		if (from == to) {
			// TODO play an error sound
			// TODO display an error message
			return;
		}
		
		final Colony sender = comboFrom.getModel().getEntry(from);
		final Colony receiver = comboTo.getModel().getEntry(to);
		// Is there enough resource in the sender colony?
		Map<Resource, BigDecimal> map = new HashMap<Resource, BigDecimal>();
		Resource[] resources = Resource.values();
		for (Resource r : resources) {
			String strVal = fields.get(r).getText();
			if ("".equals(strVal)) {
				strVal = "0";
			}
			BigDecimal value = BigDecimal.valueOf(Long.valueOf(strVal));
			map.put(r, value);
		}
		if (!ResourceHelper.enoughResourcesFor(map, sender)) {
			// TODO play an error sound
			// TODO display an error message
			return;
		}

		// Is there enough space in the target colony?
		if (!ResourceHelper.enoughSpaceFor(map, receiver)) {
			// TODO play an error sound
			// TODO display an error message
			return;
		}

		// Everything is allright, resources can be transfered
		// Remove from sender and add to receiver...
		for (Resource r : resources) {
			// Send...
			sender.updateResource(r, map.get(r).negate());
			// Receive...
			receiver.updateResource(r, map.get(r));
		}
		hide();
	}

	protected void updateSenderData() {
		if (comboFrom.getSelected() == -1) {
			return;
		}
		Colony c = colonyList.getEntry(comboFrom.getSelected());
		resourceDispFrom.setMap(ResourceHelper.cloneMap(c.getResources()));
	}

	protected void updateReseiverData() {
		if (comboTo.getSelected() == -1) {
			return;
		}
		Colony c = colonyList.getEntry(comboTo.getSelected());
		resourceDispTo.setMap(ResourceHelper.cloneMap(c.getResources()));
	}

	public void reloadList() {
		colonyList = new SimpleChangableListModel<Colony>(
				GameData.getColonies());
		comboFrom.setModel(colonyList);
		comboTo.setModel(colonyList);
		
		comboFrom.invalidateLayout();
		comboTo.invalidateLayout();
	}
}
